iT邦幫忙

第 11 屆 iThome 鐵人賽

DAY 13
1

前言

在 Day10 跟 Day11 中我們使用了 Go 提供的 os.Setenv 、 os.Unsetenv 跟 os.ExpandEnv 完成存取環境變數,因為 環境變數是系統提供的功能 ,所以系統會提供這三個 System Call

alias 也是類似的做法,但因為 alias 不是系統的功能,所以系統不會提供類似的 SetAlias、UnsetAlias 跟 ExpandAlias 給我們用,這些都要自己實作才行,今天就要使用 Map 來實作這三個 function

Alias Table

為了要做到把 gst 替換成 git status,Shell 必須自己維護一個 Alias Table 來記錄指令間的對應關係,如下圖 gst 對應到 git status、la 對應到 ls -la

如果使用者下 ls -h 時 expandAlias 就要負責把 ls 展開成 ls -l,所以最後會變成 ls -l -h

實作

如果對於 Map 的語法不太熟悉的話,建議先到我去年的 Day06-Go 語法 II 了解一下 Map,才能看懂下面的實作

set & unset

// 初始化一個空的 alias table
// 型別是 string 對應到 string
var aliasTable = map[string]string{}

func setAlias(key, value string) {
    // 把 key 跟對應的 value 丟到 alias table 裡面去
    // Ex: aliasTable["ls"] = "ls -l"
    aliasTable[key] = value
}

func unsetAlias(key string) {
    // 把 table 中的某個 key 刪掉
    // Ex: delete(aliasTable, "ls")
    delete(aliasTable, key)
}

expandAlias

func expandAlias(input string) string {
    // 把 input 的指令跟參數切開
    // input = "ls -h"
    // args = ["ls", "-h"]
    args := strings.SplitN(input, " ", 2)
    
    // 拿出指令部分,cmd = "ls"
    cmd := args[0]

    // 如果這個指令有在 alias table 裡面
    // 就會得到一個 expandedCmd(展開過後的指令) 
    // 再用新的指令取代舊的指令
    if expandedCmd, ok := aliasTable[cmd]; ok {
        // cmd = "ls"  ->  expandedCmd = "ls -l"
        // 把第一個出現的 "ls" 替換成 "ls -l" 就大功告成了
        return strings.Replace(input, cmd, expandedCmd, 1)
    }

    // 如果指令不在 alias table 裡面
    // 就什麼都不做,回傳原本的 input
    return input
}

測試

因為今天也沒有可以 Demo 的新 feature,所以寫個測試來測一下 expandAlias 有沒有正常運作

// alias_test.go

func TestExpandAlias(t *testing.T) {
    // case1: 試試看 "ls -h" 有沒有被展開成 "ls -l -h"
    setAlias("ls", "ls -l")
    input, ans := "ls -h", "ls -l -h"

    if expandAlias(input) != ans {
        t.Fail()
    }

    // case2: 試試看 "gst" 有沒有被展開成 "git status"
    setAlias("gst", "git status")
    input, ans = "gst", "git status"

    if expandAlias(input) != ans {
        t.Fail()
    }
}

看起來是沒什麼問題呢 ?

小結

View commit on Github

今天寫的扣也滿多的,而且 expandAlias 的邏輯有點複雜,對 Go 不太熟的人可能要花點時間看。如果有什麼問題的話歡迎在下方提問,沒問題的話就明天見囉


上一篇
Day12-alias 指令別名(一)
下一篇
Day14-alias 指令別名(三)
系列文
Gosh!原來用 Go 寫一個 Unix Shell 這麼簡單 共 30 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言